package cc.mrbird.febs.system.service.impl;

import cc.mrbird.febs.common.entity.DeptTree;
import cc.mrbird.febs.common.entity.DeptWithUserTree;
import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.utils.SortUtil;
import cc.mrbird.febs.common.utils.TreeUtil;
import cc.mrbird.febs.system.entity.Dept;
import cc.mrbird.febs.system.mapper.DeptMapper;
import cc.mrbird.febs.system.service.IDeptService;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author MrBird
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {

    @Override
    public List<DeptTree<Dept>> findDepts() {
        List<Dept> depts = this.baseMapper.selectList(new QueryWrapper<>());
        List<DeptTree<Dept>> trees = this.convertDepts(depts);
        return TreeUtil.buildDeptTree(trees);
    }

    @Override
    public List<DeptTree<Dept>> findDepts(Dept dept) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(dept.getDeptName()))
            queryWrapper.lambda().eq(Dept::getDeptName, dept.getDeptName());
        queryWrapper.lambda().orderByAsc(Dept::getOrderNum);

        List<Dept> depts = this.baseMapper.selectList(queryWrapper);
        List<DeptTree<Dept>> trees =  this.convertDepts(depts);
        return TreeUtil.buildDeptTree(trees);
    }

    @Override
    public List<Dept> findDepts(Dept dept, QueryRequest request) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(dept.getDeptName()))
            queryWrapper.lambda().eq(Dept::getDeptName, dept.getDeptName());
        SortUtil.handleWrapperSort(request, queryWrapper, "orderNum", FebsConstant.ORDER_ASC, true);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public void createDept(Dept dept) {
        Long parentId = dept.getParentId();
        if (parentId == null)
            dept.setParentId(0L);
        dept.setCreateTime(new Date());
        this.save(dept);
    }

    @Override
    @Transactional
    public void updateDept(Dept dept) {
        dept.setModifyTime(new Date());
        this.baseMapper.updateById(dept);
    }

    @Override
    @Transactional
    public void deleteDepts(String[] deptIds) {
       this.delete(Arrays.asList(deptIds));
    }

    private List<DeptTree<Dept>> convertDepts(List<Dept> depts){
        List<DeptTree<Dept>> trees = new ArrayList<>();
        depts.forEach(dept -> {
            DeptTree<Dept> tree = new DeptTree<>();
            tree.setId(String.valueOf(dept.getDeptId()));
            tree.setParentId(String.valueOf(dept.getParentId()));
            tree.setName(dept.getDeptName());
            tree.setData(dept);
            trees.add(tree);
        });
        return trees;
    }

    private void delete(List<String> deptIds) {
        removeByIds(deptIds);

        LambdaQueryWrapper<Dept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Dept::getParentId, deptIds);
        List<Dept> depts = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(depts)) {
            List<String> deptIdList = new ArrayList<>();
            depts.forEach(d -> deptIdList.add(String.valueOf(d.getDeptId())));
            this.delete(deptIdList);
        }
    }

	@Override
	public List<DeptWithUserTree<Dept>> findDeptsWithUser() {
		    List<Dept> depts = this.baseMapper.findDeptWithUser();
	        return this.convertDeptsWithUser(depts);
	        
	}
    
    
	private List<DeptWithUserTree<Dept>> convertDeptsWithUser(List<Dept> depts){
        List<DeptWithUserTree<Dept>> trees = new ArrayList<>();
        List<DeptWithUserTree<Dept>> userNodes = new ArrayList<>();
        depts.forEach(dept -> {
        	DeptWithUserTree<Dept> tree = new DeptWithUserTree<>();
            tree.setId(String.valueOf(dept.getDeptId()));
            tree.setParentId(String.valueOf(dept.getParentId()));
            tree.setName(dept.getDeptName());
            tree.setData(dept);
            trees.add(tree);
            
            //check has user
            if(StringUtils.isNotBlank(dept.getUserIds()))
            {
	             String[] userIds=	dept.getUserIds().split(StringPool.COMMA);
	             String[] userNames=	dept.getUserNames().split(StringPool.COMMA);
            	
            	for(int i=0;i<userIds.length;i++)
            	{
            		DeptWithUserTree<Dept> userNode= new DeptWithUserTree<>(); 
            		userNode.setId(userIds[i]);
            		userNode.setParentId(String.valueOf(dept.getDeptId()));
            		userNode.setName(userNames[i]);
            		userNode.setCheckUser(true);
            	
            		
            		Dept fakeDept=new Dept();
            		fakeDept.setDeptId(Long.valueOf(userIds[i]));
            		fakeDept.setDeptName(userNames[i]);
            		fakeDept.setParentId(dept.getDeptId());
            		userNode.setData(fakeDept);
            		
            		userNodes.add(userNode);
            	}
            }
            
        });
        
        return TreeUtil.buildDeptTreeWithUser(trees,userNodes);
    }
//    @Override
//    @Transactional
//    public Dept getDeptsIdByOU(String deptOU)
//    {
//    	 if (StringUtils.isNotBlank(deptOU))
//    	 {
//    		 LambdaQueryWrapper<Dept> queryWrapper = new LambdaQueryWrapper<>();
//    		 queryWrapper.eq(Dept::getDeptOU, deptOU);
//    		 Dept dept=baseMapper.selectOne(queryWrapper);
//    		 if(dept!=null)
//    			 return dept;
//    		 
//    		 return null;
//    	 }
//    	return null;
//    }
}
